#pragma once
#ifndef __SPORTS_MODE_COMMON_H__
#define __SPORTS_MODE_COMMON_H__
#include <sports_mode_cfg.h>
#include <stdint.h>
#include <bit_func.h>
#include <platform_toolchain.h>
#include <platform_assert.h>
typedef enum __sports_mode_data_type_t
{
    sports_mode_data_type_summary_start = 1,
    sports_mode_data_type_start_time = 1,
    sports_mode_data_type_duration = 2,
    sports_mode_data_type_mileage = 3,
    sports_mode_data_type_calorie = 4,
    sports_mode_data_type_average_speed = 5,
    sports_mode_data_type_maximum_speed = 6,
    sports_mode_data_type_average_heart_rate = 7,
    sports_mode_data_type_minimal_heart_rate = 8,
    sports_mode_data_type_maximum_heart_rate = 9,
    sports_mode_data_type_average_altitude = 10,
    sports_mode_data_type_accumulated_climbing = 11,
    sports_mode_data_type_accumulated_downhill = 12,
    sports_mode_data_type_average_pitch = 13,
    sports_mode_data_type_number_of_exercises = 14,
    sports_mode_data_type_summary_end = 15,
    sports_mode_data_type_detail_start = sports_mode_data_type_summary_end,
    sports_mode_data_type_longitude = sports_mode_data_type_detail_start,
    sports_mode_data_type_latitude = 16,
    sports_mode_data_type_heart_rate = 17,
    sports_mode_data_type_speed = 18,
    sports_mode_data_type_detail_end,
    sports_mode_data_type_summary_start_new = sports_mode_data_type_detail_end, //新增的统计信息类型
    sports_mode_data_type_pause_time = sports_mode_data_type_summary_start_new, //暂停时长 //19
    sports_mode_data_type_heart_rate_level_1_seconds,                           // 20
    sports_mode_data_type_heart_rate_level_2_seconds,                           // 21
    sports_mode_data_type_heart_rate_level_3_seconds,                           // 22
    sports_mode_data_type_heart_rate_level_4_seconds,                           // 23
    sports_mode_data_type_heart_rate_level_5_seconds,                           // 24
    sports_mode_data_type_summary_end_new,
    sports_mode_data_type_count = sports_mode_data_type_summary_end_new,

    //不上传的数据，仅用于标记数据类型
    sports_mode_data_type_total_step = 100,
    sports_mode_data_type_avg_minkm,         //平均配速
    sports_mode_data_type_maximum_minkm,     //最快配速
    sports_mode_data_type_present_hr,        //当前心率
    sports_mode_data_type_present_speed,     //当前速度
    sports_mode_data_type_present_minkm,     //当前配速
    sports_mode_data_type_present_step_freq, //当前步频
    sports_mode_data_type_precent_step,      //当前步数
} sports_mode_data_type_t;
typedef struct __sports_mode_summary_info_t
{
    //! 每一位用来标记数据是否有效
    uint8_t is_valid[ARRAY_BIT_SIZE(sports_mode_data_type_count)];
    uint8_t mode;               //!< sports_mode_mode_t
    uint8_t average_heart_rate; //!< 平均心率
    uint8_t minimal_heart_rate; //!< 最小心率
    uint8_t maximum_heart_rate; //!< 最大心率
    uint8_t average_pitch;      //!< 平均步频
    uint16_t heart_rate_level_1_seconds;
    uint16_t heart_rate_level_2_seconds;
    uint16_t heart_rate_level_3_seconds;
    uint16_t heart_rate_level_4_seconds;
    uint16_t heart_rate_level_5_seconds;

    uint16_t detail_collect_interval; //!< 采集间隔，存满后，间隔乘以2
    uint16_t pause_time;              //!< 暂停时长
    int16_t duration;                 //!< 运动持续时间，秒
    uint16_t mileage;                 //!< 里程，米
    uint16_t average_speed;           //!< 平均速度 cm/s
    uint16_t maximum_speed;           //!< 最高速度 cm/s
    uint32_t start_time;              //!< 起始时间，unix1970
    uint32_t calorie;                 //!< 卡路里，小卡
    int32_t average_altitude;         //!< 平均海拔 cm
    uint32_t accumulated_climbing;    //!< 累计爬坡 cm
    uint32_t accumulated_downhill;    //!< 累计下坡 cm
    uint32_t number_of_exercises;     //!< 运动次数

} sports_mode_summary_info_t;

PLATFORM_FORCEINLINE void sports_mode_summary_info_set_heart_rate_level_1_seconds(sports_mode_summary_info_t *thiz, uint16_t seconds)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_heart_rate_level_1_seconds, 1);
    thiz->heart_rate_level_1_seconds = seconds;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_heart_rate_level_2_seconds(sports_mode_summary_info_t *thiz, uint16_t seconds)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_heart_rate_level_2_seconds, 1);
    thiz->heart_rate_level_2_seconds = seconds;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_heart_rate_level_3_seconds(sports_mode_summary_info_t *thiz, uint16_t seconds)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_heart_rate_level_3_seconds, 1);
    thiz->heart_rate_level_3_seconds = seconds;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_heart_rate_level_4_seconds(sports_mode_summary_info_t *thiz, uint16_t seconds)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_heart_rate_level_4_seconds, 1);
    thiz->heart_rate_level_4_seconds = seconds;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_heart_rate_level_5_seconds(sports_mode_summary_info_t *thiz, uint16_t seconds)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_heart_rate_level_5_seconds, 1);
    thiz->heart_rate_level_5_seconds = seconds;
}

PLATFORM_FORCEINLINE void sports_mode_summary_info_set_minimal_heart_rate(sports_mode_summary_info_t *thiz, uint8_t minimal_heart_rate)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_minimal_heart_rate, 1);
    thiz->minimal_heart_rate = minimal_heart_rate;
}

PLATFORM_FORCEINLINE void sports_mode_summary_info_set_start_time(sports_mode_summary_info_t *thiz, uint32_t start_time)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_start_time, 1);
    thiz->start_time = start_time;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_duration(sports_mode_summary_info_t *thiz, uint16_t duration)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_duration, 1);
    thiz->duration = duration;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_mileage(sports_mode_summary_info_t *thiz, uint16_t mileage)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_mileage, 1);
    thiz->mileage = mileage;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_calorie(sports_mode_summary_info_t *thiz, uint32_t calorie)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_calorie, 1);
    thiz->calorie = calorie;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_average_speed(sports_mode_summary_info_t *thiz, uint16_t average_speed)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_average_speed, 1);
    thiz->average_speed = average_speed;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_maximum_speed(sports_mode_summary_info_t *thiz, uint16_t maximum_speed)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_maximum_speed, 1);
    thiz->maximum_speed = maximum_speed;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_average_heart_rate(sports_mode_summary_info_t *thiz, uint8_t average_heart_rate)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_average_heart_rate, 1);
    thiz->average_heart_rate = average_heart_rate;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_maximum_heart_rate(sports_mode_summary_info_t *thiz, uint8_t maximum_heart_rate)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_maximum_heart_rate, 1);
    thiz->maximum_heart_rate = maximum_heart_rate;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_average_altitude(sports_mode_summary_info_t *thiz, int32_t average_altitude)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_average_altitude, 1);
    thiz->average_altitude = average_altitude;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_accumulated_climbing(sports_mode_summary_info_t *thiz, uint32_t accumulated_climbing)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_accumulated_climbing, 1);
    thiz->accumulated_climbing = accumulated_climbing;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_accumulated_downhill(sports_mode_summary_info_t *thiz, uint32_t accumulated_downhill)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_accumulated_downhill, 1);
    thiz->accumulated_downhill = accumulated_downhill;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_average_pitch(sports_mode_summary_info_t *thiz, uint8_t average_pitch)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_average_pitch, 1);
    thiz->average_pitch = average_pitch;
}
PLATFORM_FORCEINLINE void sports_mode_summary_info_set_number_of_exercises(sports_mode_summary_info_t *thiz, uint32_t number_of_exercises)
{
    ARRAY_SET_BIT(thiz->is_valid, sports_mode_data_type_number_of_exercises, 1);
    thiz->number_of_exercises = number_of_exercises;
}
typedef PLATFORM_PACKED(struct) __sports_mode_detail_t
{
#ifdef SPORTS_MODE_HAS_GPS
    float longitude;
    float latitude;
#endif //!< SPORTS_MODE_HAS_GPS
    uint8_t heart_rate;
#ifdef SPORTS_MODE_HAS_GPS
    uint16_t speed;
#endif //!< SPORTS_MODE_HAS_GPS
}
sports_mode_detail_t;
PLATFORM_FORCEINLINE uint8_t sports_mode_get_detail_type_len(sports_mode_data_type_t data_type)
{
    Expects(data_type >= sports_mode_data_type_detail_start && data_type < sports_mode_data_type_detail_end);
    switch (data_type)
    {
#ifdef SPORTS_MODE_HAS_GPS
    case sports_mode_data_type_longitude:
        return sizeof(((sports_mode_detail_t *)0)->longitude);
    case sports_mode_data_type_latitude:
        return sizeof(((sports_mode_detail_t *)0)->latitude);
#endif //!< SPORTS_MODE_HAS_GPS
    case sports_mode_data_type_heart_rate:
        return sizeof(((sports_mode_detail_t *)0)->heart_rate);
#ifdef SPORTS_MODE_HAS_GPS
    case sports_mode_data_type_speed:
        return sizeof(((sports_mode_detail_t *)0)->speed);
#endif //!< SPORTS_MODE_HAS_GPS
    default:
        Expects(0);
        return 0;
    }
}

typedef struct __sports_mode_id_t
{
    uint16_t magic;
    uint8_t random[SPORTS_MODE_RANDOM_ID_LEN];
} sports_mode_id_t;
#endif //!< __SPORTS_MODE_COMMON_H__
